/**
 * 
 */
package org.simplextensions.scanner;

import javassist.bytecode.annotation.*;

/**
 * @author Tomasz Krzyzak, <a
 *         href="mailto:tomasz.krzyzak@gmail.com">tomasz.krzyzak@gmail.com</a>
 * @since 2009-11-15 19:01:24
 * 
 */
public class ClassScannerHelper {

	private static ArrayMemberValue memberValue;

	public static Annotation[] getAnnotationsValue(Annotation a, String memberName) {
		ArrayMemberValue amv = (ArrayMemberValue) a.getMemberValue(memberName);
		MemberValue[] value = amv.getValue();

		Annotation[] result = new Annotation[value.length];
		for (int i = 0; i < value.length; i++) {
			MemberValue mv = value[i];
			AnnotationMemberValue amv2 = (AnnotationMemberValue) mv;
			result[i] = amv2.getValue();
		}
		return result;
	}

	public static String[] getStringsValue(Annotation a, String memberName) {
		try {
			return getStringsValue(a, memberName, (String[]) getDefaultValue(a, memberName));
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	private static Object getDefaultValue(Annotation a, String memberName) throws NoSuchMethodException, ClassNotFoundException {
		return Class.forName(a.getTypeName()).getDeclaredMethod(memberName).getDefaultValue();
	}

	public static String getStringValue(Annotation a, String memberName) {
		try {
			return getStringValue(a, memberName, (String) getDefaultValue(a, memberName));
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	public static String[] getStringsValue(Annotation a, String memberName, String[] defaultValue) {
		memberValue = (ArrayMemberValue) a.getMemberValue(memberName);
		if (memberValue != null) {
			String[] result = new String[memberValue.getValue().length];
			int i = 0;
			for (MemberValue mv : memberValue.getValue()) {
				result[i++] = ((StringMemberValue) mv).getValue();
			}
			return result;
		} else
			return defaultValue;
	}

	public static String getStringValue(Annotation a, String memberName, String defaultValue) {
		StringMemberValue memberValue = (StringMemberValue) a.getMemberValue(memberName);
		if (memberValue != null) {
			return memberValue.getValue();
		} else
			return defaultValue;
	}

	public static Object getEnumValue(Annotation a, String memberName) {
		try {
			return (Enum<?>) getEnumValue(a, memberName, (Enum<?>) getDefaultValue(a, memberName));
		} catch (Exception e) {
			throw new RuntimeException(e);
		}

	}

	@SuppressWarnings({ "unchecked", "rawtypes" })
	public static <T extends Enum<?>> T getEnumValue(Annotation a, String memberName, T defaultValue) {

		Class class1;
		try {
			class1 = Class.forName(a.getTypeName()).getDeclaredMethod(memberName).getReturnType();

			EnumMemberValue memberValue = (EnumMemberValue) a.getMemberValue(memberName);
			if (memberValue != null) {
				return (T) Enum.valueOf(class1, memberValue.getValue());
			} else
				return defaultValue;
		} catch (Exception e) {
			throw new RuntimeException(e);
		}

	}

	public static Class<?> getClassValue(Annotation a, String memberName) {
		try {
			return getClassValue(a, memberName, (Class<?>) getDefaultValue(a, memberName));
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	public static Class<?>[] getClassesValue(Annotation a, String memberName) {
		try {
			return getClassesValue(a, memberName, (Class<?>[]) getDefaultValue(a, memberName));
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	public static Class<?> getClassValue(Annotation a, String memberName, Class<?> defaultValue) throws ClassNotFoundException {
		ClassMemberValue memberValue = (ClassMemberValue) a.getMemberValue(memberName);
		if (memberValue != null) {
			return Class.forName(memberValue.getValue());
		} else
			return defaultValue;
	}

	public static Class<?>[] getClassesValue(Annotation a, String memberName, Class<?>[] defaultValue) throws ClassNotFoundException {
		ArrayMemberValue memberValue = (ArrayMemberValue) a.getMemberValue(memberName);
		if (memberValue != null) {
			MemberValue[] array = memberValue.getValue();
			Class<?>[] result = new Class[array.length];
			for (int i = 0; i < array.length; i++) {
				result[i] = Class.forName(((ClassMemberValue) array[i]).getValue());
			}
			return result;
		} else
			return defaultValue;
	}

	public static Boolean getBooleanValue(Annotation a, String memberName) {
		try {
			return getBooleanValue(a, memberName, (Boolean) getDefaultValue(a, memberName));
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	public static Boolean getBooleanValue(Annotation a, String memberName, Boolean defaultValue) {
		BooleanMemberValue memberValue = (BooleanMemberValue) a.getMemberValue(memberName);
		if (memberValue != null) {
			return memberValue.getValue();
		} else
			return defaultValue;
	}

	public static Integer getIntegerValue(Annotation a, String memberName) {
		try {
			return getIntegerValue(a, memberName, (Integer) getDefaultValue(a, memberName));
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	public static Integer getIntegerValue(Annotation a, String memberName, Integer defaultValue) {
		IntegerMemberValue memberValue = (IntegerMemberValue) a.getMemberValue(memberName);
		if (memberValue != null) {
			return memberValue.getValue();
		} else
			return defaultValue;
	}

	public static Long getLongValue(Annotation a, String memberName) {
		try {
			return getLongValue(a, memberName, (Long) getDefaultValue(a, memberName));
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	public static Long getLongValue(Annotation a, String memberName, Long defaultValue) {
		LongMemberValue memberValue = (LongMemberValue) a.getMemberValue(memberName);
		if (memberValue != null) {
			return memberValue.getValue();
		} else
			return defaultValue;
	}

}
